package com.atguigu.gmall.order.service;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.CartInfoMapper;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 李旭
 * @date 2021/10/20 16:03
 * @Description:
 */
@Service
public class OrderInfoServiceImpl implements OrderInfoService {

    @Value("${ware.url}")
    private String wareUrl;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private CartInfoMapper cartInfoMapper;
    //校验库存
    @Override
    public boolean hasStock(OrderDetail orderDetail) {
        return "1".equals(HttpClientUtil.doGet(wareUrl + "/hasStock?skuId="+
                orderDetail.getSkuId() + "&num=" + orderDetail.getSkuNum()));
    }

    //二维码： 静态码 ：自己手动填写金额  没有失效的时间
    //         动态码： 自动生成对应金额的一个二维码  默认情况2小时   取消订单
    @Override
    public Long insertOrder(OrderInfo orderInfo) {
        //3:提交订单  （保存订单主表 订单详情表）

        //刚提交订单状态 未付钱
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());//要英文单词的
        //orderInfo.setOrderStatus(OrderStatus.UNPAID.getComment());//要文字的

        //订单交易编号  与第三方支付    第一：卖家  第二：买家 第三：支付宝或微信  唯一主键
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis()  + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //订单描述    手机 扫码的时候  在你的手机显示
        StringBuilder tradeBody = new StringBuilder();
        //3.1 防止页面商品价格被篡改 重新查询单个商品的价格
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        if(!CollectionUtils.isEmpty(orderDetailList)){
            for (OrderDetail orderDetail : orderDetailList) {
                BigDecimal price = productFeignClient.getPrice(orderDetail.getSkuId());
                orderDetail.setOrderPrice(price);
                tradeBody.append(orderDetail.getSkuName() + " ");//文档上这么写的的
            }
        }
        //3.2:总金额是需要重新计算的
        orderInfo.sumTotalAmount();
        //订单描述    手机 扫码的时候  在你的手机显示
        if(tradeBody.length() > 100){
            orderInfo.setTradeBody(tradeBody.substring(0,100));
        }else{
            orderInfo.setTradeBody(tradeBody.toString());
        }

        Calendar calendar = Calendar.getInstance();
        orderInfo.setCreateTime(calendar.getTime());//当前时间
        //失效时间
        calendar.add(Calendar.HOUR,2);
        orderInfo.setExpireTime(calendar.getTime());//未来2小时之后时间

        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        //1:保存订单表 才会有主键
        orderInfoMapper.insert(orderInfo);//订单主表

        //2:保存订单详情表 才会有外键   同学们自行完成    之前批量 遍历 一个一个插入
        List<String> hks = new ArrayList<>(orderDetailList.size());
        List<Long> hksByLong = new ArrayList<>(orderDetailList.size());
        orderDetailList.forEach(orderDetail -> {
            //外键
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
            hks.add(orderDetail.getSkuId().toString());
            hksByLong.add(orderDetail.getSkuId());//多定一万行 也是一眨眼就过去  SQL要不使用索引 慢了
        });

        //4、将你下的订单的商品从购物车中删除出去    Redis中 DB中
        //双写    Redis重要 同步  DB不重要 异步  打日志
        // @Async  异步排编  计算完成时的回调方法  处理返回值 处理异常
 /*       String cacheHKey = RedisConst.USER_KEY_PREFIX + orderInfo.getUserId() +
                RedisConst.USER_CART_KEY_SUFFIX;
        redisTemplate.opsForHash().delete(cacheHKey,hks.toArray());//批量

        //delete from cart_info where user_id = 3 and sku_id in (6,7,10)
        cartInfoMapper.delete(new QueryWrapper<CartInfo>()
          .eq("user_id",orderInfo.getUserId())
          .in("sku_id",hksByLong));//性能 有点差*/
        // List<String> hks   skuId是字符串类型
        //   sku_id : bigint
        //Mysql高级中 使用索引失效 ： 类型转换   where sku_id in (6,'7','10')
        //5: 开始计时 在规定时间内不给钱 取消订单  2小时  支付宝的二维码默认有效时间 为2小时
   /*     rabbitService.sendDelayedMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,
                MqConst.ROUTING_ORDER_CANCEL,orderInfo.getId(),MqConst.DELAY_TIME);*/
        return orderInfo.getId();
    }

    //订单的对象
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        //订单的ID  金额
        return orderInfoMapper.selectById(orderId);// select * 所有字段 浪费
    }


    //修改订单
    @Override
    public void updateOrderStatus(Long orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        orderInfoMapper.updateById(orderInfo);//更新
    }


    //初始化库存那边需要的数据
    public Map initWareOrder(OrderInfo orderInfo) {
        Map map = new HashMap();
        map.put("orderId", orderInfo.getId());
        map.put("consignee", orderInfo.getConsignee());
        map.put("consigneeTel", orderInfo.getConsigneeTel());
        map.put("orderComment", orderInfo.getOrderComment());
        map.put("orderBody", orderInfo.getTradeBody());
        map.put("deliveryAddress", orderInfo.getDeliveryAddress());
        map.put("paymentWay", orderInfo.getPaymentWay().equals("ONLINE")?"2":"1");
        //仓库的ID
        map.put("wareId", orderInfo.getWareId());

        List<Map> details = orderInfo.getOrderDetailList().stream().map(orderDetail -> {
            Map m = new HashMap();
            m.put("skuId",orderDetail.getSkuId());
            m.put("skuNum",orderDetail.getSkuNum());
            m.put("skuName",orderDetail.getSkuName());
            return m;
        }).collect(Collectors.toList());
        map.put("details",details);
        return map;
    }
    //初始化库存那边需要的数据
    @Override
    public Map initWareOrder(Long orderId) {
        OrderInfo orderInfo = getOrderInfoAndDetails(orderId);
        return initWareOrder(orderInfo);
    }

    //开始拆单  超级难   一张订单 拆成N多张订单
    //                  原始订单       拆后N多个订单
    @Override
    public List<OrderInfo> orderSplit(Long orderId, String wareSkuMap) {
        //父订单 原始订单
        OrderInfo orderInfoOrigin = getOrderInfoAndDetails(orderId);


        List<Map> wareSkuMapList = JSONObject.parseArray(wareSkuMap, Map.class);
        List<OrderInfo> subOrderInfoList = wareSkuMapList.stream().map(map -> {
            //子订单
            OrderInfo subOrderInfo = new OrderInfo();

            //父订单的所有的属性全都复制给子订单
            BeanUtils.copyProperties(orderInfoOrigin, subOrderInfo);
            //ID
            subOrderInfo.setId(null);//由数据库生成
            //parent_order_id
            subOrderInfo.setParentOrderId(orderInfoOrigin.getId());

            //仓库ID
            Object wareId = map.get("wareId");
            subOrderInfo.setWareId(String.valueOf(wareId));
            //订单详情
            //wareSkuMap  [
            //              {"wareId":"1","skuIds":["7"]}
            //              {"wareId":"2","skuIds":["10","14"]}    ,
            //            ]
            //              wareId 1号仓库ID   skuIds:库存集合    wareId 2号仓库ID  skuIds:库存集合

            // 如果是1号仓库  长度是1
            // 如果是2号仓库  长度是2
            List<String> skuIds = (List<String>) map.get("skuIds");
            // 长度是3  原始订单订单详情  父订单表的订单详情
            List<OrderDetail> orderDetailList = orderInfoOrigin.getOrderDetailList();
            // 子订单的订单详情
            List<OrderDetail> subOrderDetailList = orderDetailList.stream().filter(orderDetail -> {
                if(skuIds.contains(String.valueOf(orderDetail.getSkuId()))){
                    return true;
                }else{
                    return false;
                }
            }).collect(Collectors.toList());
            //子订单主表
            subOrderInfo.setOrderDetailList(subOrderDetailList);
            //总金额
            subOrderInfo.sumTotalAmount();
            //保存子订单到DB中  返回值 是子订单的ID
            orderInfoMapper.insert(subOrderInfo);
            //子订单详情的外键
            subOrderDetailList.forEach(subOrderDetail -> {
                subOrderDetail.setOrderId(subOrderInfo.getId());
                orderDetailMapper.updateById(subOrderDetail);
            });
            return subOrderInfo;
        }).collect(Collectors.toList());
        //更新父订单的订单状态为 已拆单
        updateOrderStatus(orderInfoOrigin.getId(),ProcessStatus.SPLIT);
        return subOrderInfoList;
    }

    //获取订单及订单详情集合
    public OrderInfo getOrderInfoAndDetails(Long orderId){
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if(null != orderInfo){
            orderInfo.setOrderDetailList(orderDetailMapper.selectList(new QueryWrapper<OrderDetail>()
              .eq("order_id",orderId)));
        }
        return orderInfo;
    }


    @Autowired
    private RabbitService rabbitService;
}
